package com.tenebrous.jestic.compents.annotations;

import com.alibaba.fastjson.JSON;
import com.tenebrous.jestic.entity.framwork.meber.organ.OrgUser;
import com.tenebrous.jestic.entity.framwork.system.SysLogOper;
import com.tenebrous.jestic.service.framwork.system.SysLogService;
import com.rain.ops.sdk.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 *
 */
@Slf4j
@Aspect
@Component
public class WeblogAspect {

    @Value("${weblog.enabled:false}")
    private boolean enabled;

    @Autowired
    private SysLogService logService;
    /**
     * 定义切点
     *
     * @author wuzhangshan
     * @date 2018-6-11
     */
    @Pointcut("@annotation(com.tenebrous.jestic.compents.annotations.Weblog)")//指向自定义注解路径
    public void pointcut() {
    }


    /**
     * 环绕通知
     *
     * @param pjp
     * @throws Throwable
     * @author wuzhangshan
     * @date 2018-6-11
     */
    @Around("pointcut()")
    public Object aroud(ProceedingJoinPoint pjp) throws Throwable {

        Date starttime = new Date();
        Object obj = pjp.proceed();
        Date endtime = new Date();

        try {
            if(this.enabled){
                HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
                HttpSession session = request.getSession(true);
                String sessionid = session.getId();
                Object uobj = session.getAttribute(sessionid);

                Signature signature = pjp.getSignature();
                MethodSignature methodSignature = (MethodSignature)signature;
                Weblog annotation = methodSignature.getMethod().getAnnotation(Weblog.class);

                String url = request.getRequestURL().toString();
                String method = request.getMethod();
                String clsMethod = signature.getDeclaringTypeName()+"."+signature.getName();
                String description = annotation.description();
                String weblogEnum = annotation.method().getValue();
                String ip = request.getHeader("X-Forwarded-For");
                if(StringUtils.isBlank(ip)){
                    ip = request.getHeader("X-Real-IP");
                    if(StringUtils.isBlank(ip)){
                        ip = request.getRemoteAddr();
                    }
                }
                SysLogOper olog = new SysLogOper();
                olog.setId(UUIDUtils.randomUUID());
                olog.setIp(ip);
                olog.setStype(weblogEnum);
                olog.setAction(clsMethod);
                olog.setRemark(description);
                olog.setSessionid(session.getId());
                olog.setUrl(String.format("[%s] %s", method ,url));
                olog.setClientInfo(request.getHeader("User-Agent"));
                olog.setParamstring(JSON.toJSONString(request.getParameterMap()));
                olog.setQuerystring(request.getQueryString());
                olog.setExeStartTime(starttime);
                olog.setExeEndTime(endtime);
                olog.setCreateDate(endtime);
                olog.setMilliseconds(endtime.getTime() - starttime.getTime());
                if(uobj != null){
                    OrgUser ouser = (OrgUser) uobj;
                    olog.setCreateUserid(ouser.getId());
                    olog.setCreateUsername(ouser.getUsername());
                }
                logService.saveOperLogSelective(olog);
            }
        } catch (Throwable throwable) {
            log.error("WeblogAspect异常", throwable);
        }
        return obj;
    }
}
